/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License specifically applicable to
 * this software at http://developer.yahoo.com/yslow/license.txt, or the general
 * form at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is: YSlow
 *
 * The Initial Developer of the Original Code is Yahoo! Inc.
 *
 * Copyright (C) 2007, Yahoo! Inc. All Rights Reserved.
 *
 * Contributor(s):
 * ***** END LICENSE BLOCK ***** */

FBL.ns(function() { with (FBL) {
Firebug.YSlowModule = extend(Firebug.Module,
{
	// Called when browser starts.
	initialize: function() {
		//setDprint(9);
		this.initPrefs();
		YSLOW.Utils.toggleStatusBar(YSLOW.getPref("yslow.hidestatusbar"));
		YSLOW.Utils.patchNetPanel();
	},


    //Function is called when browser starts and when page changes.
    initContext: function(context) {
    },


	// Called when the user switches browser tabs.
	showContext: function(browser, context) {
		YSLOW.Utils.clearStatusBar();
		if ( FirebugContext.getPanel('yslow') ) {
			FirebugContext.getPanel('yslow').restoreStatusBar(context);
		}
	},


    loadedContext: function(context) {
        // Makes detach work.
		if ( ! context.yslowContext ) {
	        context.yslowContext = gLatestYSlowContext;
		}
    },


    reattachContext: function(context) {
        // Makes detach work.
        if ( ! FirebugContext.getPanel("yslow").document.yslowContext ) {
			// Save a pointer back to this object from the iframe's document:
			FirebugContext.getPanel("yslow").document.yslowPanel = FirebugContext.getPanel("yslow");
			FirebugContext.getPanel("yslow").document.yslowContext = FirebugContext.yslowContext;

			YSLOW.Utils.loadCss("chrome://yslow/content/yslow.css", FirebugContext.getPanel("yslow").document);
        }
    },


    destroyContext: function(context) {
        // Makes detach work.
        gLatestYSlowContext = undefined;
    },


    // Called when the browser closes.
    shutdown: function() {
		if(Firebug.getPref('defaultPanelName')=='YSlow') {
			Firebug.setPref('defaultPanelName','console');
		}
    },

	getDefaultView: function() {
        if ( FirebugChrome.$("ysCompsButton").checked ) {
		    return "ysCompsButton";
        }
        else if ( FirebugChrome.$("ysStatsButton").checked ) {
		    return "ysStatsButton";
        }
        else {
			FirebugChrome.$("ysPerfButton").checked = true;
		    return "ysPerfButton";
        }
	},

	// Stop the response time timer.
	// Kick off downloading components if Autorun is on.
    yslowOnload: function(runOnce) {
		var now = Number(new Date());
		var t_start = FirebugContext.browser.t_start;

		// This causes initializeNode to be called, thus creating FirebugContext.yslowContext.
		FirebugContext.getPanel('yslow');

		FirebugContext.yslowContext.PAGE["readyState"] = 'complete';

		// Display the page load time.
		if ( t_start ) {
			FirebugContext.yslowContext.t_done = now - t_start;
			YSLOW.Utils.setStatusBar( FirebugContext.yslowContext.t_done/1000 + "s", "yslowStatusTime");
			FirebugContext.browser.t_start = undefined;
		}

		if ( YSLOW.getPref("yslow.autorun") || runOnce == true ) {
			FirebugContext.yslowContext.peel(Firebug.YSlowModule.getDefaultView());
		}
    },

	// Start the response time timer.
    yslowUnload: function() {
		YSLOW.Utils.clearStatusBar();
		// Save the time this page UNloads, so we can determine the total load time of the NEXT page.
		// We save it in the browser object so that it is persistant ACROSS page loads, but separated
		// from one browser tab to another.
		FirebugContext.browser.t_start = Number(new Date());
    },

	// Called when page changes.
	// Putting the onload listener here ensures that the components are downloaded even
	// when the YSlow panel is NOT selected, and even when Firebug is closed (but enabled).
	// Also, it does it late enough that the window is available.
	watchWindow: function(context, win) {
		FirebugContext.window.addEventListener("load", this.yslowOnload, false);
		FirebugContext.window.addEventListener("beforeunload", this.yslowUnload, false);
	},

    showPanel: function(browser, panel) {
        var bMe = panel && panel.name == "yslow";
        var myButtons = browser.chrome.$("fbYSlowButtons");
	    // This removes our buttons.
        collapse(myButtons, !bMe);
    },

    yslowPerformance: function(bOpen)
    {
		if ( bOpen ) {
			Firebug.toggleBar();
			Firebug.showPanel(FirebugChrome.getCurrentBrowser(), FirebugContext.getPanel('yslow'));
		}
        FirebugChrome.$("ysPerfButton").checked = true;
		FirebugContext.yslowContext.peel("ysPerfButton");
    },

    yslowComponents: function()
    {
        FirebugChrome.$("ysCompsButton").checked = true;
		FirebugContext.yslowContext.peel("ysCompsButton");
    },

    yslowStats: function()
    {
        FirebugChrome.$("ysStatsButton").checked = true;
		FirebugContext.yslowContext.peel("ysStatsButton");
    },

	initPrefs: function() {
		// Read persistent options and set them in our YSLOW object.
		YSLOW.prefs = {};
	},

	yslowTools: function(menuitem) {
		if ( "JSLint" == menuitem.label ) {
			YSLOW.JSLint.loadJSLint();
		}
		else if ( "All JS" == menuitem.label ) {
			YSLOW.Tools.loadAllJS();
		}
		else if ( "All CSS" == menuitem.label ) {
			YSLOW.Tools.loadAllCSS();
		}
		else if ( "Printable View" == menuitem.label ) {
			YSLOW.Tools.printable();
		}
	},

	onClickIcon: function(context, event, ele)
    {
        if (event.button != 0) {
            return;
        }
        else if (isControl(event)) {
            Firebug.toggleDetachBar(true);
        }
        else {
            Firebug.toggleBar();
            Firebug.tabBrowser.selectedBrowser.chrome.selectPanel('yslow');
        }
    },

	onClickStatusGrade: function(context, event, ele)
    {
        if (event.button != 0) {
            return;
        }
        else if (isControl(event)) {
            Firebug.toggleDetachBar(true);
        }
        else {
        	Firebug.tabBrowser.selectedBrowser.chrome.selectPanel('yslow');
            Firebug.showBar(true);

            Firebug.YSlowModule.yslowPerformance();		//Lets go to the performance view.
        }
    },

    onClickStatusSize: function(context, event, ele)
    {
        if (event.button != 0) {
            return;
        }
        else if (isControl(event)) {
            Firebug.toggleDetachBar(true);
        }
        else {
        	Firebug.tabBrowser.selectedBrowser.chrome.selectPanel('yslow');
            Firebug.showBar(true);

            Firebug.YSlowModule.yslowStats();			//Lets go to the stats view.
        }
    },


	// When an option changes, this is called.
	updateOption: function(name, value) {
		// Handle hide/show of statusbar info
		if ( "yslow.hidestatusbar" == name ) {
			YSLOW.Utils.toggleStatusBar(value);
		}
	},

    //This function will be called when the "About YSlow" menu item is clicked from Options menu.
	yslowHelp: function(menuitem) {
		if ( "YSlow Help" == menuitem.label ) {
			gBrowser.selectedTab = gBrowser.addTab("http://developer.yahoo.com/yslow/help/");
		}
		else if ( "YSlow FAQ" == menuitem.label ) {
			gBrowser.selectedTab = gBrowser.addTab("http://developer.yahoo.com/yslow/faq.html");
		}
		else if ( "YSlow Blog" == menuitem.label ) {
			gBrowser.selectedTab = gBrowser.addTab("http://developer.yahoo.net/blog/archives/performance/");
		}
		else if ( "YSlow Community" == menuitem.label ) {
			gBrowser.selectedTab = gBrowser.addTab("http://tech.groups.yahoo.com/group/exceptional-performance/");
		}
		else if ( "Send Feedback" == menuitem.label ) {
			gBrowser.selectedTab = gBrowser.addTab("http://developer.yahoo.com/yslow/feedback.html");
		}
		else if ( "YSlow Home" == menuitem.label ) {
			gBrowser.selectedTab = gBrowser.addTab("http://developer.yahoo.com/yslow");
		}
	}
});


function YSlowPanel() {}
YSlowPanel.prototype = extend(Firebug.Panel,
{
    name: "yslow",
    title: "YSlow",
    searchable: true,
    editable: false,

	// This is only called once per browser tab.
	initialize: function(context, doc) {
		dprint(9, "YSlowPanel.initialize: enter");

	    this.context = context;
	    this.document = doc;
    	this.panelNode = doc.createElement("div");
	    this.panelNode.ownerPanel = this;
    	setClass(this.panelNode, "panelNode panelNode-" + this.name);
	    doc.body.appendChild(this.panelNode);

		// Make some CSS and JS available from WITHIN the panel's document.
		YSLOW.Utils.loadCss("chrome://yslow/content/yslow.css", this.document);

	    this.initializeNode(this.panelNode);
	},


	// Initialize the panel. This is called when the Panel is activated and
	// whenever the browser document changes (new URL, reload).
	initializeNode: function() {
        dprint(9, "YSlowPanel.initializeNode: enter");
        if ( FirebugContext.yslowContext ) {
            eprint("ERROR: YSlowPanel.initializeNode: FirebugContext.yslowContext already exists!");
            return;
        }

		// Create a YSlowContext for this instance.
		FirebugContext.yslowContext = new YSLOW.YSlowContext(this);

		FirebugContext.yslowContext.PAGE["initializeNode"] = true;

		// Save a pointer back to this object from the iframe's document:
		this.document.yslowPanel = this;
		this.document.yslowContext = FirebugContext.yslowContext;

		// Display a little "about" text.
		var sHtml;
		if ( FirebugContext.yslowContext["warning"] ) {
			sHtml = FirebugContext.yslowContext["warning"];
		}
        else if ( YSLOW.getPref("yslow.autorun") ) {
        	sHtml = "<div style=\"background: #D5FFFF; padding: 10px 10px 10px 10px; line-height: 120%\">"+
        				"Autorun Mode: <b>On</b>"+
        				"<br /><br />"+
        				"<div style=\"float: left;\"><img src='chrome://firebug/skin/loading_16.gif'></div>"+
						"<div style=\"margin-left: 30px;\">"+
							"The page is loading....<br />"+
							"<b>YSlow</b> will start automatically, once the page has finished loading."+
						"</div>"+
					"</div>";
        }
        else {
            sHtml = "<div style=\"font-size: 14pt; color: #E76300; margin: 2px;\"><img style=\"padding-right: 5px\"  src=\"chrome://yslow/content/logo_32x32.png\" align=\"absbottom\"/>YSlow for Firebug</div>"+
            		"<br />"+
            		"<div style=\"background: #D5FFFF; padding: 10px 10px 10px 10px; line-height: 190%; width: 800px\">"+
            			"Click Performance, Stats, or Components to have YSlow analyze the page.<br />"+
            			"Select the \"Autorun\" option to make YSlow start automatically."+
            		"</div>"+
            		"<div style=\"font-size: 8pt; margin-top: 20px\">Copyright &copy; 2007 Yahoo! Inc. All rights reserved.<img style=\"padding-left: 520px\" src=\"chrome://yslow/content/yahooLogo.gif\" /></div>";
        }
		FirebugContext.yslowContext.addButtonView('panel_about', "<div class=about>" + sHtml + "</div>");
	},

	// This is called whenever the panel comes into view. Like toggling between browser tabs.
    show: function() {
        dprint(9, "YSlowPanel.show: enter");

		gLatestYSlowContext = FirebugContext.yslowContext;  // save this to make detach work

		this.restoreButtons();

		// There is only ONE DOCUMENT shared by all browser tabs. So if the user opens two
		// browser tabs, we have to restore the appropriate yslowContext when switching between tabs.
		this.document.yslowContext = FirebugContext.yslowContext;

        FirebugContext.yslowContext.show();
    },


	restoreButtons: function() {
		// Set/Restore button state.
		if ( FirebugContext.yslowContext.defaultview ) {
			// If the page has been peeled, select the button that corresponds to
			// the most recent view, and enable the Tools menu.
			if ( "ysPerfButton" == FirebugContext.yslowContext.defaultview ) {
				FirebugChrome.$("ysPerfButton").checked = true;
			}
			else if ( "ysCompsButton" == FirebugContext.yslowContext.defaultview ) {
			    FirebugChrome.$("ysCompsButton").checked = true;
			}
			else if ( "ysStatsButton" == FirebugContext.yslowContext.defaultview ) {
		        FirebugChrome.$("ysStatsButton").checked = true;
			}
			// If we've peeled the page, we can enable the Tools menu.
			FirebugChrome.window.document.getElementById('ysToolsMenu').disabled = false;
		}
		else {
			// If the page has NOT been peeled, deselect all buttons and disable the Tools menu.
			FirebugChrome.$("ysPerfButton").checked = false;
		    FirebugChrome.$("ysCompsButton").checked = false;
        	FirebugChrome.$("ysStatsButton").checked = false;
			FirebugChrome.window.document.getElementById('ysToolsMenu').disabled = true;
		}
	},


	// Display the right stats in the status bar when switching between browser tabs.
	restoreStatusBar: function(fbContext) {
		if ( !fbContext || !fbContext.yslowContext ) {
			return;
		}

		if ( fbContext.yslowContext.PAGE["overallScore"] ) {
	        var score = fbContext.yslowContext.PAGE["overallScore"];
    	    var grade = YSLOW.Utils.prettyScore(score, false, true);
	        YSLOW.Utils.setStatusBar(grade, "yslowStatusGrade");
		}

		if ( fbContext.yslowContext.PAGE["totalSize"] ) {
	        var size = YSLOW.Utils.formatFloat( ( fbContext.yslowContext.PAGE["totalSize"] ? fbContext.yslowContext.PAGE["totalSize"]/1000 : 0 ), 1, "K");
	        YSLOW.Utils.setStatusBar(size, "yslowStatusSize");
		}

		if ( fbContext.yslowContext.t_done ) {
			YSLOW.Utils.setStatusBar( fbContext.yslowContext.t_done/1000 + "s", "yslowStatusTime");
		}
	},


	////////////////////////////////////////////////////////////////////////////
	//   OPTIONS MENU (NOT the right-click one in the status bar - that's in yslowOverlay.xul)
	////////////////////////////////////////////////////////////////////////////

	// This is called EVERY time the options menu is opened.
	// Return an array of menu option objects.
    getOptionsMenuItems: function()
    {
        return [
			this.optionMenuYSlow("Autorun", "yslow.autorun"),
			this.optionMenuYSlow("Hide Statusbar Info", "yslow.hidestatusbar"),
        ];
    },

    getContextMenuItems: function(nada, target)
    {
    	var items = [];

        //Check if the user has right clicked on a URL. If not lets not show any menu here.
        if ( target && target.toString().indexOf("http://") == -1 && target.toString().indexOf("https://") == -1 && target.toString().indexOf("ftp://") == -1 ) {
        	return null;
        }
        items.push(
            "-",
            {label: "OpenInTab", command: bindFixed(this.openNewTab, FBL, target) },
            {label: "Open in New Window", nol10n: true, command: bindFixed(this.openNewWindow, FBL, target) }
        );

        return items;
    },

	// Return an option menu item.
	optionMenuYSlow: function(label, option) {

		var value = Firebug.getPref(option);
		// bindFixed is from Firebug. It helps to pass the args along.
	    return { label: label, nol10n: true, type: "checkbox", checked: value, command: bindFixed(this.setPrefYSlow, Firebug, option, !value) }
	},

	//open urls in a new browser tab.
	openNewWindow: function(url) {
		if (url) {
			window.open(url,"_blank");
		}
    },

	//open urls in a new browser tab.
	openNewTab: function(url) {
		if (url) {
			gBrowser.selectedTab = gBrowser.addTab(url);
		}
        else {
			gBrowser.selectedTab = gBrowser.addTab();
		}

        return gBrowser.selectedTab;
    },

	openLink: function(url) {
        YSLOW.Utils.openLink(url);
	},

	setPrefYSlow: function(name, value) {
		Firebug.setPref(name, value);
	},

	// When an option changes, this is called.
	updateOption: function(name, value) {
		// Save the option value in our memory object.
		// (The permanent value is saved automatically.)
		FirebugContext.yslowContext[name] = value;
	},

    // tooltip
    showInfoTip: function (infoTip, target, x, y) {

        if (target.nodeName === "A" && target.rel && (target.rel === 'image' || target.rel === 'cssimage')) {
            return Firebug.InfoTip.populateImageInfoTip(infoTip, target.href);
        }
    },

    // global search
    search: function (text) {

        if (!text) {
            delete this.currentSearch;
            return false;
        }

        var row;
        if (this.currentSearch && text == this.currentSearch.text) {
            row = this.currentSearch.findNext(true);
        } else {
            this.currentSearch = new TextSearch(this.panelNode, function(node){return node.parentNode;});
            row = this.currentSearch.find(text);
        }

        if (row) {
            var sel = this.document.defaultView.getSelection();
            sel.removeAllRanges();
            sel.addRange(this.currentSearch.range);
            scrollIntoCenterView(row, this.panelNode);
            return true;
        } else {
            return false;
        }

    }


});

function isURLEncodedFile(file, text)
{
    return (text && text.indexOf("Content-Type: application/x-www-form-urlencoded") != -1)
        || findHeader(file.requestHeaders, "Content-Type") == "application/x-www-form-urlencoded";
}

Firebug.registerModule(Firebug.YSlowModule);
Firebug.registerPanel(YSlowPanel);

}});
